package com.ds.lens.data.service;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.ds.lens.data.common.asserts.Asserts;
import com.ds.lens.data.common.constant.Constants;
import com.ds.lens.data.common.constant.EventSourceEnum;
import com.ds.lens.data.common.constant.EventStateEnum;
import com.ds.lens.data.common.document.Notify;
import com.ds.lens.data.common.document.dto.MonitorEvent;
import com.ds.lens.data.common.document.dto.MonitorKey;
import com.ds.lens.data.kafka.KafkaProducer;
import com.ds.lens.data.service.dao.LensMonitorDao;
import com.ds.lens.data.service.dao.LensMonitorNotifyDao;
import com.ds.lens.data.service.dao.entity.LensMonitor;
import com.ds.lens.data.service.dao.entity.LensMonitorNotify;
import com.ds.lens.data.vo.in.PagedConditionInVO;
import com.ds.lens.data.vo.in.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * Description:
 *
 * @author WeiShaoying
 * @date 2019-11-05
 */
class BaseService {
    /**
     * 元数据服务用户接口
     */
    static final String API_BASE_INFO = "/rest/ms/user?limit=20&q=$PARAM";
    static final int HTTP_TIMEOUT = 5000;

    @Autowired
    LensMonitorDao lensMonitorDao;

    @Autowired
    LensMonitorNotifyDao lensMonitorNotifyDao;

    @Autowired
    KafkaProducer kafkaProducer;

    @Value("${lens.kafka.event.topic}")
    String eventTopic;

    <T> T getPageCondition(PagedConditionInVO<T> conditionInVO) {
        Asserts.assertNotNull(conditionInVO.getCondition(), Constants.ErrorCode.PARAM_ERROR, "Condition can not be null.");
        PageHelper.startPage(conditionInVO.getPage().getIndex(), conditionInVO.getPage().getSize());
        return conditionInVO.getCondition();
    }

    void checkUserApplication(User user) {
        if (!user.isAdmin()) {
            Asserts.assertFalse(CollectionUtils.isEmpty(user.getApplicationIds()), Constants.ErrorCode.USER_PERMISSIONS);
        }
    }

    void checkUserApplication(User user, Long applicationId) {
        if (!user.isAdmin()) {
            checkUserApplication(user);
            Asserts.assertTrue(user.getApplicationIds().contains(applicationId), Constants.ErrorCode.USER_PERMISSIONS);
        }
    }

    void checkUserApplication(User user, List<Long> applicationIds) {
        if (!user.isAdmin()) {
            checkUserApplication(user);
            Asserts.assertTrue(user.getApplicationIds().containsAll(applicationIds), Constants.ErrorCode.USER_PERMISSIONS);
        }
    }

    List<LensMonitor> checkUserMonitorId(List<Long> ids, User user) {
        List<LensMonitor> monitor = lensMonitorDao.selectByPrimaryKeys(ids);
        Asserts.assertNotEmpty(monitor, Constants.ErrorCode.SYSTEM_EXCEPTION);
        List<Long> applicationIds = new ArrayList<>(ids.size());
        monitor.forEach(lensMonitor -> applicationIds.add(lensMonitor.getApplicationId()));
        checkUserApplication(user, applicationIds);
        return monitor;
    }

    List<LensMonitor> checkUserMonitors(List<LensMonitor> monitors, User user) {
        Asserts.assertNotEmpty(monitors, Constants.ErrorCode.SYSTEM_EXCEPTION);
        List<Long> applicationIds = Lists.newArrayListWithCapacity(monitors.size());
        monitors.forEach(lensMonitor -> applicationIds.add(lensMonitor.getApplicationId()));
        checkUserApplication(user, applicationIds);
        return monitors;
    }

    void sendEvent(LensMonitor lensMonitor, String content) {
        LensMonitorNotify lensMonitorNotify = lensMonitorNotifyDao.selectByMonitorId(lensMonitor.getId());
        MonitorEvent monitorEvent = MonitorEvent.builder()
                .uid(UUID.randomUUID().toString())
                .monitorKey(new MonitorKey(lensMonitor.getId(), lensMonitor.getVersion()))
                .monitorName(lensMonitor.getName())
                .tags(!StringUtils.isEmpty(lensMonitor.getTags()) ? Arrays.asList(lensMonitor.getTags().split(",")) : null)
                .appId(lensMonitor.getApplicationId())
                .state(EventStateEnum.INFO)
                .timeStamp(System.currentTimeMillis())
                .notify(Notify.builder()
                        .content(content)
                        .title(lensMonitorNotify.getTitle())
                        .channel(lensMonitorNotify.getChannel())
                        .channelContent(lensMonitorNotify.getChannelContent())
                        .build())
                .eventSourceEnum(EventSourceEnum.LENS_EVENT)
                .isNotify(false)
                .build();
        kafkaProducer.sendMessage(eventTopic, null, JSONObject.toJSONString(monitorEvent));
    }
}
